/*
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package javax.swing;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.KeyboardFocusManager;
import java.awt.Frame;
import java.awt.Point;
import java.awt.HeadlessException;
import java.awt.Window;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.awt.event.WindowListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Vector;
import javax.swing.plaf.OptionPaneUI;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameAdapter;
import javax.accessibility.*;

import static javax.swing.ClientPropertyKey.PopupFactory_FORCE_HEAVYWEIGHT_POPUP;

/**
 * <code>JOptionPane</code> makes it easy to pop up a standard dialog box that prompts users for a
 * value or informs them of something. For information about using <code>JOptionPane</code>, see <a
 * href="https://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html">How to Make
 * Dialogs</a>, a section in <em>The Java Tutorial</em>.
 *
 * <p>
 *
 * While the <code>JOptionPane</code> class may appear complex because of the large number of
 * methods, almost all uses of this class are one-line calls to one of the static
 * <code>showXxxDialog</code> methods shown below: <blockquote>
 *
 *
 * <table border=1 summary="Common JOptionPane method names and their descriptions"> <tr> <th>Method
 * Name</th> <th>Description</th> </tr> <tr> <td>showConfirmDialog</td> <td>Asks a confirming
 * question, like yes/no/cancel.</td> </tr> <tr> <td>showInputDialog</td> <td>Prompt for some
 * input.</td> </tr> <tr> <td>showMessageDialog</td> <td>Tell the user about something that has
 * happened.</td> </tr> <tr> <td>showOptionDialog</td> <td>The Grand Unification of the above
 * three.</td> </tr> </table>
 *
 * </blockquote> Each of these methods also comes in a <code>showInternalXXX</code> flavor, which
 * uses an internal frame to hold the dialog box (see {@link JInternalFrame}). Multiple convenience
 * methods have also been defined -- overloaded versions of the basic methods that use different
 * parameter lists. <p> All dialogs are modal. Each <code>showXxxDialog</code> method blocks the
 * caller until the user's interaction is complete.
 *
 * <table cellspacing=6 cellpadding=4 border=0 style="float:right" summary="layout"> <tr> <td
 * style="background-color:#FFe0d0" rowspan=2>icon</td> <td style="background-color:#FFe0d0">message</td>
 * </tr> <tr> <td style="background-color:#FFe0d0">input value</td> </tr> <tr> <td
 * style="background-color:#FFe0d0" colspan=2>option buttons</td> </tr> </table>
 *
 * The basic appearance of one of these dialog boxes is generally similar to the picture at the
 * right, although the various look-and-feels are ultimately responsible for the final result.  In
 * particular, the look-and-feels will adjust the layout to accommodate the option pane's
 * <code>ComponentOrientation</code> property. <br style="clear:all"> <p> <b>Parameters:</b><br> The
 * parameters to these methods follow consistent patterns: <blockquote> <dl compact>
 * <dt>parentComponent<dd> Defines the <code>Component</code> that is to be the parent of this
 * dialog box. It is used in two ways: the <code>Frame</code> that contains it is used as the
 * <code>Frame</code> parent for the dialog box, and its screen coordinates are used in the
 * placement of the dialog box. In general, the dialog box is placed just below the component. This
 * parameter may be <code>null</code>, in which case a default <code>Frame</code> is used as the
 * parent, and the dialog will be centered on the screen (depending on the {@literal L&F}). <dt><a
 * name=message>message</a><dd> A descriptive message to be placed in the dialog box. In the most
 * common usage, message is just a <code>String</code> or <code>String</code> constant. However, the
 * type of this parameter is actually <code>Object</code>. Its interpretation depends on its type:
 * <dl compact> <dt>Object[]<dd>An array of objects is interpreted as a series of messages (one per
 * object) arranged in a vertical stack. The interpretation is recursive -- each object in the array
 * is interpreted according to its type. <dt>Component<dd>The <code>Component</code> is displayed in
 * the dialog. <dt>Icon<dd>The <code>Icon</code> is wrapped in a <code>JLabel</code> and displayed
 * in the dialog. <dt>others<dd>The object is converted to a <code>String</code> by calling its
 * <code>toString</code> method. The result is wrapped in a <code>JLabel</code> and displayed. </dl>
 * <dt>messageType<dd>Defines the style of the message. The Look and Feel manager may lay out the
 * dialog differently depending on this value, and will often provide a default icon. The possible
 * values are: <ul> <li><code>ERROR_MESSAGE</code> <li><code>INFORMATION_MESSAGE</code>
 * <li><code>WARNING_MESSAGE</code> <li><code>QUESTION_MESSAGE</code> <li><code>PLAIN_MESSAGE</code>
 * </ul> <dt>optionType<dd>Defines the set of option buttons that appear at the bottom of the dialog
 * box: <ul> <li><code>DEFAULT_OPTION</code> <li><code>YES_NO_OPTION</code>
 * <li><code>YES_NO_CANCEL_OPTION</code> <li><code>OK_CANCEL_OPTION</code> </ul> You aren't limited
 * to this set of option buttons.  You can provide any buttons you want using the options parameter.
 * <dt>options<dd>A more detailed description of the set of option buttons that will appear at the
 * bottom of the dialog box. The usual value for the options parameter is an array of
 * <code>String</code>s. But the parameter type is an array of <code>Objects</code>. A button is
 * created for each object depending on its type: <dl compact> <dt>Component<dd>The component is
 * added to the button row directly. <dt>Icon<dd>A <code>JButton</code> is created with this as its
 * label. <dt>other<dd>The <code>Object</code> is converted to a string using its
 * <code>toString</code> method and the result is used to label a <code>JButton</code>. </dl>
 * <dt>icon<dd>A decorative icon to be placed in the dialog box. A default value for this is
 * determined by the <code>messageType</code> parameter. <dt>title<dd>The title for the dialog box.
 * <dt>initialValue<dd>The default selection (input value). </dl> </blockquote> <p> When the
 * selection is changed, <code>setValue</code> is invoked, which generates a
 * <code>PropertyChangeEvent</code>. <p> If a <code>JOptionPane</code> has configured to all input
 * <code>setWantsInput</code> the bound property <code>JOptionPane.INPUT_VALUE_PROPERTY</code> can
 * also be listened to, to determine when the user has input or selected a value. <p> When one of
 * the <code>showXxxDialog</code> methods returns an integer, the possible values are: <ul>
 * <li><code>YES_OPTION</code> <li><code>NO_OPTION</code> <li><code>CANCEL_OPTION</code>
 * <li><code>OK_OPTION</code> <li><code>CLOSED_OPTION</code> </ul> <b>Examples:</b> <dl> <dt>Show an
 * error dialog that displays the message, 'alert': <dd><code> JOptionPane.showMessageDialog(null,
 * "alert", "alert", JOptionPane.ERROR_MESSAGE); </code> <dt>Show an internal information dialog
 * with the message, 'information':
 * <dd><pre>
 * JOptionPane.showInternalMessageDialog(frame, "information",
 *             "information", JOptionPane.INFORMATION_MESSAGE);
 * </pre>
 * <dt>Show an information panel with the options yes/no and message 'choose one':
 * <dd><pre>JOptionPane.showConfirmDialog(null,
 *             "choose one", "choose one", JOptionPane.YES_NO_OPTION);
 * </pre>
 * <dt>Show an internal information dialog with the options yes/no/cancel and message 'please choose
 * one' and title information:
 * <dd><pre>JOptionPane.showInternalConfirmDialog(frame,
 *             "please choose one", "information",
 *             JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE);
 * </pre>
 * <dt>Show a warning dialog with the options OK, CANCEL, title 'Warning', and message 'Click OK to
 * continue':
 * <dd><pre>
 * Object[] options = { "OK", "CANCEL" };
 * JOptionPane.showOptionDialog(null, "Click OK to continue", "Warning",
 *             JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
 *             null, options, options[0]);
 * </pre>
 * <dt>Show a dialog asking the user to type in a String: <dd><code> String inputValue =
 * JOptionPane.showInputDialog("Please input a value"); </code> <dt>Show a dialog asking the user to
 * select a String:
 * <dd><pre>
 * Object[] possibleValues = { "First", "Second", "Third" };<br>
 * Object selectedValue = JOptionPane.showInputDialog(null,
 *             "Choose one", "Input",
 *             JOptionPane.INFORMATION_MESSAGE, null,
 *             possibleValues, possibleValues[0]);
 * </pre><p>
 * </dl> <b>Direct Use:</b><br> To create and use an <code>JOptionPane</code> directly, the standard
 * pattern is roughly as follows:
 * <pre>
 *     JOptionPane pane = new JOptionPane(<i>arguments</i>);
 *     pane.set<i>.Xxxx(...); // Configure</i>
 *     JDialog dialog = pane.createDialog(<i>parentComponent, title</i>);
 *     dialog.show();
 *     Object selectedValue = pane.getValue();
 *     if(selectedValue == null)
 *       return CLOSED_OPTION;
 *     <i>//If there is <b>not</b> an array of option buttons:</i>
 *     if(options == null) {
 *       if(selectedValue instanceof Integer)
 *          return ((Integer)selectedValue).intValue();
 *       return CLOSED_OPTION;
 *     }
 *     <i>//If there is an array of option buttons:</i>
 *     for(int counter = 0, maxCounter = options.length;
 *        counter &lt; maxCounter; counter++) {
 *        if(options[counter].equals(selectedValue))
 *        return counter;
 *     }
 *     return CLOSED_OPTION;
 * </pre>
 * <p> <strong>Warning:</strong> Swing is not thread safe. For more information see <a
 * href="package-summary.html#threading">Swing's Threading Policy</a>. <p> <strong>Warning:</strong>
 * Serialized objects of this class will not be compatible with future Swing releases. The current
 * serialization support is appropriate for short term storage or RMI between applications running
 * the same version of Swing.  As of 1.4, support for long term storage of all JavaBeans&trade; has
 * been added to the <code>java.beans</code> package. Please see {@link java.beans.XMLEncoder}.
 *
 * @author James Gosling
 * @author Scott Violet
 * @beaninfo attribute: isContainer true description: A component which implements standard dialog
 * box controls.
 * @see JInternalFrame
 */
public class JOptionPane extends JComponent implements Accessible {

  /**
   * @see #getUIClassID
   * @see #readObject
   */
  private static final String uiClassID = "OptionPaneUI";

  /**
   * Indicates that the user has not yet selected a value.
   */
  public static final Object UNINITIALIZED_VALUE = "uninitializedValue";

  //
  // Option types
  //

  /**
   * Type meaning Look and Feel should not supply any options -- only
   * use the options from the <code>JOptionPane</code>.
   */
  public static final int DEFAULT_OPTION = -1;
  /**
   * Type used for <code>showConfirmDialog</code>.
   */
  public static final int YES_NO_OPTION = 0;
  /**
   * Type used for <code>showConfirmDialog</code>.
   */
  public static final int YES_NO_CANCEL_OPTION = 1;
  /**
   * Type used for <code>showConfirmDialog</code>.
   */
  public static final int OK_CANCEL_OPTION = 2;

  //
  // Return values.
  //
  /**
   * Return value from class method if YES is chosen.
   */
  public static final int YES_OPTION = 0;
  /**
   * Return value from class method if NO is chosen.
   */
  public static final int NO_OPTION = 1;
  /**
   * Return value from class method if CANCEL is chosen.
   */
  public static final int CANCEL_OPTION = 2;
  /**
   * Return value form class method if OK is chosen.
   */
  public static final int OK_OPTION = 0;
  /**
   * Return value from class method if user closes window without selecting
   * anything, more than likely this should be treated as either a
   * <code>CANCEL_OPTION</code> or <code>NO_OPTION</code>.
   */
  public static final int CLOSED_OPTION = -1;

  //
  // Message types. Used by the UI to determine what icon to display,
  // and possibly what behavior to give based on the type.
  //
  /**
   * Used for error messages.
   */
  public static final int ERROR_MESSAGE = 0;
  /**
   * Used for information messages.
   */
  public static final int INFORMATION_MESSAGE = 1;
  /**
   * Used for warning messages.
   */
  public static final int WARNING_MESSAGE = 2;
  /**
   * Used for questions.
   */
  public static final int QUESTION_MESSAGE = 3;
  /**
   * No icon is used.
   */
  public static final int PLAIN_MESSAGE = -1;

  /**
   * Bound property name for <code>icon</code>.
   */
  public static final String ICON_PROPERTY = "icon";
  /**
   * Bound property name for <code>message</code>.
   */
  public static final String MESSAGE_PROPERTY = "message";
  /**
   * Bound property name for <code>value</code>.
   */
  public static final String VALUE_PROPERTY = "value";
  /**
   * Bound property name for <code>option</code>.
   */
  public static final String OPTIONS_PROPERTY = "options";
  /**
   * Bound property name for <code>initialValue</code>.
   */
  public static final String INITIAL_VALUE_PROPERTY = "initialValue";
  /**
   * Bound property name for <code>type</code>.
   */
  public static final String MESSAGE_TYPE_PROPERTY = "messageType";
  /**
   * Bound property name for <code>optionType</code>.
   */
  public static final String OPTION_TYPE_PROPERTY = "optionType";
  /**
   * Bound property name for <code>selectionValues</code>.
   */
  public static final String SELECTION_VALUES_PROPERTY = "selectionValues";
  /**
   * Bound property name for <code>initialSelectionValue</code>.
   */
  public static final String INITIAL_SELECTION_VALUE_PROPERTY = "initialSelectionValue";
  /**
   * Bound property name for <code>inputValue</code>.
   */
  public static final String INPUT_VALUE_PROPERTY = "inputValue";
  /**
   * Bound property name for <code>wantsInput</code>.
   */
  public static final String WANTS_INPUT_PROPERTY = "wantsInput";

  /**
   * Icon used in pane.
   */
  transient protected Icon icon;
  /**
   * Message to display.
   */
  transient protected Object message;
  /**
   * Options to display to the user.
   */
  transient protected Object[] options;
  /**
   * Value that should be initially selected in <code>options</code>.
   */
  transient protected Object initialValue;
  /**
   * Message type.
   */
  protected int messageType;
  /**
   * Option type, one of <code>DEFAULT_OPTION</code>,
   * <code>YES_NO_OPTION</code>,
   * <code>YES_NO_CANCEL_OPTION</code> or
   * <code>OK_CANCEL_OPTION</code>.
   */
  protected int optionType;
  /**
   * Currently selected value, will be a valid option, or
   * <code>UNINITIALIZED_VALUE</code> or <code>null</code>.
   */
  transient protected Object value;
  /**
   * Array of values the user can choose from. Look and feel will
   * provide the UI component to choose this from.
   */
  protected transient Object[] selectionValues;
  /**
   * Value the user has input.
   */
  protected transient Object inputValue;
  /**
   * Initial value to select in <code>selectionValues</code>.
   */
  protected transient Object initialSelectionValue;
  /**
   * If true, a UI widget will be provided to the user to get input.
   */
  protected boolean wantsInput;


  /**
   * Shows a question-message dialog requesting input from the user. The
   * dialog uses the default frame, which usually means it is centered on
   * the screen.
   *
   * @param message the <code>Object</code> to display
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public static String showInputDialog(Object message)
      throws HeadlessException {
    return showInputDialog(null, message);
  }

  /**
   * Shows a question-message dialog requesting input from the user, with
   * the input value initialized to <code>initialSelectionValue</code>. The
   * dialog uses the default frame, which usually means it is centered on
   * the screen.
   *
   * @param message the <code>Object</code> to display
   * @param initialSelectionValue the value used to initialize the input field
   * @since 1.4
   */
  public static String showInputDialog(Object message, Object initialSelectionValue) {
    return showInputDialog(null, message, initialSelectionValue);
  }

  /**
   * Shows a question-message dialog requesting input from the user
   * parented to <code>parentComponent</code>.
   * The dialog is displayed on top of the <code>Component</code>'s
   * frame, and is usually positioned below the <code>Component</code>.
   *
   * @param parentComponent the parent <code>Component</code> for the dialog
   * @param message the <code>Object</code> to display
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public static String showInputDialog(Component parentComponent,
      Object message) throws HeadlessException {
    return showInputDialog(parentComponent, message, UIManager.getString(
        "OptionPane.inputDialogTitle", parentComponent), QUESTION_MESSAGE);
  }

  /**
   * Shows a question-message dialog requesting input from the user and
   * parented to <code>parentComponent</code>. The input value will be
   * initialized to <code>initialSelectionValue</code>.
   * The dialog is displayed on top of the <code>Component</code>'s
   * frame, and is usually positioned below the <code>Component</code>.
   *
   * @param parentComponent the parent <code>Component</code> for the dialog
   * @param message the <code>Object</code> to display
   * @param initialSelectionValue the value used to initialize the input field
   * @since 1.4
   */
  public static String showInputDialog(Component parentComponent, Object message,
      Object initialSelectionValue) {
    return (String) showInputDialog(parentComponent, message,
        UIManager.getString("OptionPane.inputDialogTitle",
            parentComponent), QUESTION_MESSAGE, null, null,
        initialSelectionValue);
  }

  /**
   * Shows a dialog requesting input from the user parented to
   * <code>parentComponent</code> with the dialog having the title
   * <code>title</code> and message type <code>messageType</code>.
   *
   * @param parentComponent the parent <code>Component</code> for the dialog
   * @param message the <code>Object</code> to display
   * @param title the <code>String</code> to display in the dialog title bar
   * @param messageType the type of message that is to be displayed: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public static String showInputDialog(Component parentComponent,
      Object message, String title, int messageType)
      throws HeadlessException {
    return (String) showInputDialog(parentComponent, message, title,
        messageType, null, null, null);
  }

  /**
   * Prompts the user for input in a blocking dialog where the
   * initial selection, possible selections, and all other options can
   * be specified. The user will able to choose from
   * <code>selectionValues</code>, where <code>null</code> implies the
   * user can input
   * whatever they wish, usually by means of a <code>JTextField</code>.
   * <code>initialSelectionValue</code> is the initial value to prompt
   * the user with. It is up to the UI to decide how best to represent
   * the <code>selectionValues</code>, but usually a
   * <code>JComboBox</code>, <code>JList</code>, or
   * <code>JTextField</code> will be used.
   *
   * @param parentComponent the parent <code>Component</code> for the dialog
   * @param message the <code>Object</code> to display
   * @param title the <code>String</code> to display in the dialog title bar
   * @param messageType the type of message to be displayed: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @param icon the <code>Icon</code> image to display
   * @param selectionValues an array of <code>Object</code>s that gives the possible selections
   * @param initialSelectionValue the value used to initialize the input field
   * @return user's input, or <code>null</code> meaning the user canceled the input
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public static Object showInputDialog(Component parentComponent,
      Object message, String title, int messageType, Icon icon,
      Object[] selectionValues, Object initialSelectionValue)
      throws HeadlessException {
    JOptionPane pane = new JOptionPane(message, messageType,
        OK_CANCEL_OPTION, icon,
        null, null);

    pane.setWantsInput(true);
    pane.setSelectionValues(selectionValues);
    pane.setInitialSelectionValue(initialSelectionValue);
    pane.setComponentOrientation(((parentComponent == null) ?
        getRootFrame() : parentComponent).getComponentOrientation());

    int style = styleFromMessageType(messageType);
    JDialog dialog = pane.createDialog(parentComponent, title, style);

    pane.selectInitialValue();
    dialog.show();
    dialog.dispose();

    Object value = pane.getInputValue();

    if (value == UNINITIALIZED_VALUE) {
      return null;
    }
    return value;
  }

  /**
   * Brings up an information-message dialog titled "Message".
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used
   * @param message the <code>Object</code> to display
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public static void showMessageDialog(Component parentComponent,
      Object message) throws HeadlessException {
    showMessageDialog(parentComponent, message, UIManager.getString(
        "OptionPane.messageDialogTitle", parentComponent),
        INFORMATION_MESSAGE);
  }

  /**
   * Brings up a dialog that displays a message using a default
   * icon determined by the <code>messageType</code> parameter.
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used
   * @param message the <code>Object</code> to display
   * @param title the title string for the dialog
   * @param messageType the type of message to be displayed: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public static void showMessageDialog(Component parentComponent,
      Object message, String title, int messageType)
      throws HeadlessException {
    showMessageDialog(parentComponent, message, title, messageType, null);
  }

  /**
   * Brings up a dialog displaying a message, specifying all parameters.
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used
   * @param message the <code>Object</code> to display
   * @param title the title string for the dialog
   * @param messageType the type of message to be displayed: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @param icon an icon to display in the dialog that helps the user identify the kind of message
   * that is being displayed
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public static void showMessageDialog(Component parentComponent,
      Object message, String title, int messageType, Icon icon)
      throws HeadlessException {
    showOptionDialog(parentComponent, message, title, DEFAULT_OPTION,
        messageType, icon, null, null);
  }

  /**
   * Brings up a dialog with the options <i>Yes</i>,
   * <i>No</i> and <i>Cancel</i>; with the
   * title, <b>Select an Option</b>.
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used
   * @param message the <code>Object</code> to display
   * @return an integer indicating the option selected by the user
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public static int showConfirmDialog(Component parentComponent,
      Object message) throws HeadlessException {
    return showConfirmDialog(parentComponent, message,
        UIManager.getString("OptionPane.titleText"),
        YES_NO_CANCEL_OPTION);
  }

  /**
   * Brings up a dialog where the number of choices is determined
   * by the <code>optionType</code> parameter.
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used
   * @param message the <code>Object</code> to display
   * @param title the title string for the dialog
   * @param optionType an int designating the options available on the dialog:
   * <code>YES_NO_OPTION</code>, <code>YES_NO_CANCEL_OPTION</code>, or
   * <code>OK_CANCEL_OPTION</code>
   * @return an int indicating the option selected by the user
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public static int showConfirmDialog(Component parentComponent,
      Object message, String title, int optionType)
      throws HeadlessException {
    return showConfirmDialog(parentComponent, message, title, optionType,
        QUESTION_MESSAGE);
  }

  /**
   * Brings up a dialog where the number of choices is determined
   * by the <code>optionType</code> parameter, where the
   * <code>messageType</code>
   * parameter determines the icon to display.
   * The <code>messageType</code> parameter is primarily used to supply
   * a default icon from the Look and Feel.
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used.
   * @param message the <code>Object</code> to display
   * @param title the title string for the dialog
   * @param optionType an integer designating the options available on the dialog:
   * <code>YES_NO_OPTION</code>, <code>YES_NO_CANCEL_OPTION</code>, or
   * <code>OK_CANCEL_OPTION</code>
   * @param messageType an integer designating the kind of message this is; primarily used to
   * determine the icon from the pluggable Look and Feel: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @return an integer indicating the option selected by the user
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public static int showConfirmDialog(Component parentComponent,
      Object message, String title, int optionType, int messageType)
      throws HeadlessException {
    return showConfirmDialog(parentComponent, message, title, optionType,
        messageType, null);
  }

  /**
   * Brings up a dialog with a specified icon, where the number of
   * choices is determined by the <code>optionType</code> parameter.
   * The <code>messageType</code> parameter is primarily used to supply
   * a default icon from the look and feel.
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used
   * @param message the Object to display
   * @param title the title string for the dialog
   * @param optionType an int designating the options available on the dialog:
   * <code>YES_NO_OPTION</code>, <code>YES_NO_CANCEL_OPTION</code>, or
   * <code>OK_CANCEL_OPTION</code>
   * @param messageType an int designating the kind of message this is, primarily used to determine
   * the icon from the pluggable Look and Feel: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @param icon the icon to display in the dialog
   * @return an int indicating the option selected by the user
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public static int showConfirmDialog(Component parentComponent,
      Object message, String title, int optionType,
      int messageType, Icon icon) throws HeadlessException {
    return showOptionDialog(parentComponent, message, title, optionType,
        messageType, icon, null, null);
  }

  /**
   * Brings up a dialog with a specified icon, where the initial
   * choice is determined by the <code>initialValue</code> parameter and
   * the number of choices is determined by the <code>optionType</code>
   * parameter.
   * <p>
   * If <code>optionType</code> is <code>YES_NO_OPTION</code>,
   * or <code>YES_NO_CANCEL_OPTION</code>
   * and the <code>options</code> parameter is <code>null</code>,
   * then the options are
   * supplied by the look and feel.
   * <p>
   * The <code>messageType</code> parameter is primarily used to supply
   * a default icon from the look and feel.
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed;  if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used
   * @param message the <code>Object</code> to display
   * @param title the title string for the dialog
   * @param optionType an integer designating the options available on the dialog:
   * <code>DEFAULT_OPTION</code>, <code>YES_NO_OPTION</code>, <code>YES_NO_CANCEL_OPTION</code>, or
   * <code>OK_CANCEL_OPTION</code>
   * @param messageType an integer designating the kind of message this is, primarily used to
   * determine the icon from the pluggable Look and Feel: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @param icon the icon to display in the dialog
   * @param options an array of objects indicating the possible choices the user can make; if the
   * objects are components, they are rendered properly; non-<code>String</code> objects are
   * rendered using their <code>toString</code> methods; if this parameter is <code>null</code>, the
   * options are determined by the Look and Feel
   * @param initialValue the object that represents the default selection for the dialog; only
   * meaningful if <code>options</code> is used; can be <code>null</code>
   * @return an integer indicating the option chosen by the user, or <code>CLOSED_OPTION</code> if
   * the user closed the dialog
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public static int showOptionDialog(Component parentComponent,
      Object message, String title, int optionType, int messageType,
      Icon icon, Object[] options, Object initialValue)
      throws HeadlessException {
    JOptionPane pane = new JOptionPane(message, messageType,
        optionType, icon,
        options, initialValue);

    pane.setInitialValue(initialValue);
    pane.setComponentOrientation(((parentComponent == null) ?
        getRootFrame() : parentComponent).getComponentOrientation());

    int style = styleFromMessageType(messageType);
    JDialog dialog = pane.createDialog(parentComponent, title, style);

    pane.selectInitialValue();
    dialog.show();
    dialog.dispose();

    Object selectedValue = pane.getValue();

    if (selectedValue == null) {
      return CLOSED_OPTION;
    }
    if (options == null) {
      if (selectedValue instanceof Integer) {
        return ((Integer) selectedValue).intValue();
      }
      return CLOSED_OPTION;
    }
    for (int counter = 0, maxCounter = options.length;
        counter < maxCounter; counter++) {
      if (options[counter].equals(selectedValue)) {
        return counter;
      }
    }
    return CLOSED_OPTION;
  }

  /**
   * Creates and returns a new <code>JDialog</code> wrapping
   * <code>this</code> centered on the <code>parentComponent</code>
   * in the <code>parentComponent</code>'s frame.
   * <code>title</code> is the title of the returned dialog.
   * The returned <code>JDialog</code> will not be resizable by the
   * user, however programs can invoke <code>setResizable</code> on
   * the <code>JDialog</code> instance to change this property.
   * The returned <code>JDialog</code> will be set up such that
   * once it is closed, or the user clicks on one of the buttons,
   * the optionpane's value property will be set accordingly and
   * the dialog will be closed.  Each time the dialog is made visible,
   * it will reset the option pane's value property to
   * <code>JOptionPane.UNINITIALIZED_VALUE</code> to ensure the
   * user's subsequent action closes the dialog properly.
   *
   * @param parentComponent determines the frame in which the dialog is displayed; if the
   * <code>parentComponent</code> has no <code>Frame</code>, a default <code>Frame</code> is used
   * @param title the title string for the dialog
   * @return a new <code>JDialog</code> containing this instance
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public JDialog createDialog(Component parentComponent, String title)
      throws HeadlessException {
    int style = styleFromMessageType(getMessageType());
    return createDialog(parentComponent, title, style);
  }

  /**
   * Creates and returns a new parentless <code>JDialog</code>
   * with the specified title.
   * The returned <code>JDialog</code> will not be resizable by the
   * user, however programs can invoke <code>setResizable</code> on
   * the <code>JDialog</code> instance to change this property.
   * The returned <code>JDialog</code> will be set up such that
   * once it is closed, or the user clicks on one of the buttons,
   * the optionpane's value property will be set accordingly and
   * the dialog will be closed.  Each time the dialog is made visible,
   * it will reset the option pane's value property to
   * <code>JOptionPane.UNINITIALIZED_VALUE</code> to ensure the
   * user's subsequent action closes the dialog properly.
   *
   * @param title the title string for the dialog
   * @return a new <code>JDialog</code> containing this instance
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   * @since 1.6
   */
  public JDialog createDialog(String title) throws HeadlessException {
    int style = styleFromMessageType(getMessageType());
    JDialog dialog = new JDialog((Dialog) null, title, true);
    initDialog(dialog, style, null);
    return dialog;
  }

  private JDialog createDialog(Component parentComponent, String title,
      int style)
      throws HeadlessException {

    final JDialog dialog;

    Window window = JOptionPane.getWindowForComponent(parentComponent);
    if (window instanceof Frame) {
      dialog = new JDialog((Frame) window, title, true);
    } else {
      dialog = new JDialog((Dialog) window, title, true);
    }
    if (window instanceof SwingUtilities.SharedOwnerFrame) {
      WindowListener ownerShutdownListener =
          SwingUtilities.getSharedOwnerFrameShutdownListener();
      dialog.addWindowListener(ownerShutdownListener);
    }
    initDialog(dialog, style, parentComponent);
    return dialog;
  }

  private void initDialog(final JDialog dialog, int style, Component parentComponent) {
    dialog.setComponentOrientation(this.getComponentOrientation());
    Container contentPane = dialog.getContentPane();

    contentPane.setLayout(new BorderLayout());
    contentPane.add(this, BorderLayout.CENTER);
    dialog.setResizable(false);
    if (JDialog.isDefaultLookAndFeelDecorated()) {
      boolean supportsWindowDecorations =
          UIManager.getLookAndFeel().getSupportsWindowDecorations();
      if (supportsWindowDecorations) {
        dialog.setUndecorated(true);
        getRootPane().setWindowDecorationStyle(style);
      }
    }
    dialog.pack();
    dialog.setLocationRelativeTo(parentComponent);

    final PropertyChangeListener listener = new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent event) {
        // Let the defaultCloseOperation handle the closing
        // if the user closed the window without selecting a button
        // (newValue = null in that case).  Otherwise, close the dialog.
        if (dialog.isVisible() && event.getSource() == JOptionPane.this &&
            (event.getPropertyName().equals(VALUE_PROPERTY)) &&
            event.getNewValue() != null &&
            event.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) {
          dialog.setVisible(false);
        }
      }
    };

    WindowAdapter adapter = new WindowAdapter() {
      private boolean gotFocus = false;

      public void windowClosing(WindowEvent we) {
        setValue(null);
      }

      public void windowClosed(WindowEvent e) {
        removePropertyChangeListener(listener);
        dialog.getContentPane().removeAll();
      }

      public void windowGainedFocus(WindowEvent we) {
        // Once window gets focus, set initial focus
        if (!gotFocus) {
          selectInitialValue();
          gotFocus = true;
        }
      }
    };
    dialog.addWindowListener(adapter);
    dialog.addWindowFocusListener(adapter);
    dialog.addComponentListener(new ComponentAdapter() {
      public void componentShown(ComponentEvent ce) {
        // reset value to ensure closing works properly
        setValue(JOptionPane.UNINITIALIZED_VALUE);
      }
    });

    addPropertyChangeListener(listener);
  }


  /**
   * Brings up an internal confirmation dialog panel. The dialog
   * is a information-message dialog titled "Message".
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used
   * @param message the object to display
   */
  public static void showInternalMessageDialog(Component parentComponent,
      Object message) {
    showInternalMessageDialog(parentComponent, message, UIManager.
        getString("OptionPane.messageDialogTitle",
            parentComponent), INFORMATION_MESSAGE);
  }

  /**
   * Brings up an internal dialog panel that displays a message
   * using a default icon determined by the <code>messageType</code>
   * parameter.
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used
   * @param message the <code>Object</code> to display
   * @param title the title string for the dialog
   * @param messageType the type of message to be displayed: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   */
  public static void showInternalMessageDialog(Component parentComponent,
      Object message, String title,
      int messageType) {
    showInternalMessageDialog(parentComponent, message, title, messageType, null);
  }

  /**
   * Brings up an internal dialog panel displaying a message,
   * specifying all parameters.
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used
   * @param message the <code>Object</code> to display
   * @param title the title string for the dialog
   * @param messageType the type of message to be displayed: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @param icon an icon to display in the dialog that helps the user identify the kind of message
   * that is being displayed
   */
  public static void showInternalMessageDialog(Component parentComponent,
      Object message,
      String title, int messageType,
      Icon icon) {
    showInternalOptionDialog(parentComponent, message, title, DEFAULT_OPTION,
        messageType, icon, null, null);
  }

  /**
   * Brings up an internal dialog panel with the options <i>Yes</i>, <i>No</i>
   * and <i>Cancel</i>; with the title, <b>Select an Option</b>.
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used
   * @param message the <code>Object</code> to display
   * @return an integer indicating the option selected by the user
   */
  public static int showInternalConfirmDialog(Component parentComponent,
      Object message) {
    return showInternalConfirmDialog(parentComponent, message,
        UIManager.getString("OptionPane.titleText"),
        YES_NO_CANCEL_OPTION);
  }

  /**
   * Brings up a internal dialog panel where the number of choices
   * is determined by the <code>optionType</code> parameter.
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used
   * @param message the object to display in the dialog; a <code>Component</code> object is rendered
   * as a <code>Component</code>; a <code>String</code> object is rendered as a string; other
   * objects are converted to a <code>String</code> using the <code>toString</code> method
   * @param title the title string for the dialog
   * @param optionType an integer designating the options available on the dialog:
   * <code>YES_NO_OPTION</code>, or <code>YES_NO_CANCEL_OPTION</code>
   * @return an integer indicating the option selected by the user
   */
  public static int showInternalConfirmDialog(Component parentComponent,
      Object message, String title,
      int optionType) {
    return showInternalConfirmDialog(parentComponent, message, title, optionType,
        QUESTION_MESSAGE);
  }

  /**
   * Brings up an internal dialog panel where the number of choices
   * is determined by the <code>optionType</code> parameter, where
   * the <code>messageType</code> parameter determines the icon to display.
   * The <code>messageType</code> parameter is primarily used to supply
   * a default icon from the Look and Feel.
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used
   * @param message the object to display in the dialog; a <code>Component</code> object is rendered
   * as a <code>Component</code>; a <code>String</code> object is rendered as a string; other
   * objects are converted to a <code>String</code> using the <code>toString</code> method
   * @param title the title string for the dialog
   * @param optionType an integer designating the options available on the dialog:
   * <code>YES_NO_OPTION</code>, or <code>YES_NO_CANCEL_OPTION</code>
   * @param messageType an integer designating the kind of message this is, primarily used to
   * determine the icon from the pluggable Look and Feel: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @return an integer indicating the option selected by the user
   */
  public static int showInternalConfirmDialog(Component parentComponent,
      Object message,
      String title, int optionType,
      int messageType) {
    return showInternalConfirmDialog(parentComponent, message, title, optionType,
        messageType, null);
  }

  /**
   * Brings up an internal dialog panel with a specified icon, where
   * the number of choices is determined by the <code>optionType</code>
   * parameter.
   * The <code>messageType</code> parameter is primarily used to supply
   * a default icon from the look and feel.
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the parentComponent has no Frame, a default <code>Frame</code> is
   * used
   * @param message the object to display in the dialog; a <code>Component</code> object is rendered
   * as a <code>Component</code>; a <code>String</code> object is rendered as a string; other
   * objects are converted to a <code>String</code> using the <code>toString</code> method
   * @param title the title string for the dialog
   * @param optionType an integer designating the options available on the dialog:
   * <code>YES_NO_OPTION</code>, or <code>YES_NO_CANCEL_OPTION</code>.
   * @param messageType an integer designating the kind of message this is, primarily used to
   * determine the icon from the pluggable Look and Feel: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @param icon the icon to display in the dialog
   * @return an integer indicating the option selected by the user
   */
  public static int showInternalConfirmDialog(Component parentComponent,
      Object message,
      String title, int optionType,
      int messageType, Icon icon) {
    return showInternalOptionDialog(parentComponent, message, title, optionType,
        messageType, icon, null, null);
  }

  /**
   * Brings up an internal dialog panel with a specified icon, where
   * the initial choice is determined by the <code>initialValue</code>
   * parameter and the number of choices is determined by the
   * <code>optionType</code> parameter.
   * <p>
   * If <code>optionType</code> is <code>YES_NO_OPTION</code>, or
   * <code>YES_NO_CANCEL_OPTION</code>
   * and the <code>options</code> parameter is <code>null</code>,
   * then the options are supplied by the Look and Feel.
   * <p>
   * The <code>messageType</code> parameter is primarily used to supply
   * a default icon from the look and feel.
   *
   * @param parentComponent determines the <code>Frame</code> in which the dialog is displayed; if
   * <code>null</code>, or if the <code>parentComponent</code> has no <code>Frame</code>, a default
   * <code>Frame</code> is used
   * @param message the object to display in the dialog; a <code>Component</code> object is rendered
   * as a <code>Component</code>; a <code>String</code> object is rendered as a string. Other
   * objects are converted to a <code>String</code> using the <code>toString</code> method
   * @param title the title string for the dialog
   * @param optionType an integer designating the options available on the dialog:
   * <code>YES_NO_OPTION</code>, or <code>YES_NO_CANCEL_OPTION</code>
   * @param messageType an integer designating the kind of message this is; primarily used to
   * determine the icon from the pluggable Look and Feel: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @param icon the icon to display in the dialog
   * @param options an array of objects indicating the possible choices the user can make; if the
   * objects are components, they are rendered properly; non-<code>String</code> objects are
   * rendered using their <code>toString</code> methods; if this parameter is <code>null</code>, the
   * options are determined by the Look and Feel
   * @param initialValue the object that represents the default selection for the dialog; only
   * meaningful if <code>options</code> is used; can be <code>null</code>
   * @return an integer indicating the option chosen by the user, or <code>CLOSED_OPTION</code> if
   * the user closed the Dialog
   */
  public static int showInternalOptionDialog(Component parentComponent,
      Object message,
      String title, int optionType,
      int messageType, Icon icon,
      Object[] options, Object initialValue) {
    JOptionPane pane = new JOptionPane(message, messageType,
        optionType, icon, options, initialValue);
    pane.putClientProperty(PopupFactory_FORCE_HEAVYWEIGHT_POPUP,
        Boolean.TRUE);
    Component fo = KeyboardFocusManager.getCurrentKeyboardFocusManager().
        getFocusOwner();

    pane.setInitialValue(initialValue);

    JInternalFrame dialog =
        pane.createInternalFrame(parentComponent, title);
    pane.selectInitialValue();
    dialog.setVisible(true);

        /* Since all input will be blocked until this dialog is dismissed,
         * make sure its parent containers are visible first (this component
         * is tested below).  This is necessary for JApplets, because
         * because an applet normally isn't made visible until after its
         * start() method returns -- if this method is called from start(),
         * the applet will appear to hang while an invisible modal frame
         * waits for input.
         */
    if (dialog.isVisible() && !dialog.isShowing()) {
      Container parent = dialog.getParent();
      while (parent != null) {
        if (parent.isVisible() == false) {
          parent.setVisible(true);
        }
        parent = parent.getParent();
      }
    }

    // Use reflection to get Container.startLWModal.
    try {
      Method method = AccessController.doPrivileged(new ModalPrivilegedAction(
          Container.class, "startLWModal"));
      if (method != null) {
        method.invoke(dialog, (Object[]) null);
      }
    } catch (IllegalAccessException ex) {
    } catch (IllegalArgumentException ex) {
    } catch (InvocationTargetException ex) {
    }

    if (parentComponent instanceof JInternalFrame) {
      try {
        ((JInternalFrame) parentComponent).setSelected(true);
      } catch (java.beans.PropertyVetoException e) {
      }
    }

    Object selectedValue = pane.getValue();

    if (fo != null && fo.isShowing()) {
      fo.requestFocus();
    }
    if (selectedValue == null) {
      return CLOSED_OPTION;
    }
    if (options == null) {
      if (selectedValue instanceof Integer) {
        return ((Integer) selectedValue).intValue();
      }
      return CLOSED_OPTION;
    }
    for (int counter = 0, maxCounter = options.length;
        counter < maxCounter; counter++) {
      if (options[counter].equals(selectedValue)) {
        return counter;
      }
    }
    return CLOSED_OPTION;
  }

  /**
   * Shows an internal question-message dialog requesting input from
   * the user parented to <code>parentComponent</code>. The dialog
   * is displayed in the <code>Component</code>'s frame,
   * and is usually positioned below the <code>Component</code>.
   *
   * @param parentComponent the parent <code>Component</code> for the dialog
   * @param message the <code>Object</code> to display
   */
  public static String showInternalInputDialog(Component parentComponent,
      Object message) {
    return showInternalInputDialog(parentComponent, message, UIManager.
            getString("OptionPane.inputDialogTitle", parentComponent),
        QUESTION_MESSAGE);
  }

  /**
   * Shows an internal dialog requesting input from the user parented
   * to <code>parentComponent</code> with the dialog having the title
   * <code>title</code> and message type <code>messageType</code>.
   *
   * @param parentComponent the parent <code>Component</code> for the dialog
   * @param message the <code>Object</code> to display
   * @param title the <code>String</code> to display in the dialog title bar
   * @param messageType the type of message that is to be displayed: ERROR_MESSAGE,
   * INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE, or PLAIN_MESSAGE
   */
  public static String showInternalInputDialog(Component parentComponent,
      Object message, String title, int messageType) {
    return (String) showInternalInputDialog(parentComponent, message, title,
        messageType, null, null, null);
  }

  /**
   * Prompts the user for input in a blocking internal dialog where
   * the initial selection, possible selections, and all other
   * options can be specified. The user will able to choose from
   * <code>selectionValues</code>, where <code>null</code>
   * implies the user can input
   * whatever they wish, usually by means of a <code>JTextField</code>.
   * <code>initialSelectionValue</code> is the initial value to prompt
   * the user with. It is up to the UI to decide how best to represent
   * the <code>selectionValues</code>, but usually a
   * <code>JComboBox</code>, <code>JList</code>, or
   * <code>JTextField</code> will be used.
   *
   * @param parentComponent the parent <code>Component</code> for the dialog
   * @param message the <code>Object</code> to display
   * @param title the <code>String</code> to display in the dialog title bar
   * @param messageType the type of message to be displayed: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @param icon the <code>Icon</code> image to display
   * @param selectionValues an array of <code>Objects</code> that gives the possible selections
   * @param initialSelectionValue the value used to initialize the input field
   * @return user's input, or <code>null</code> meaning the user canceled the input
   */
  public static Object showInternalInputDialog(Component parentComponent,
      Object message, String title, int messageType, Icon icon,
      Object[] selectionValues, Object initialSelectionValue) {
    JOptionPane pane = new JOptionPane(message, messageType,
        OK_CANCEL_OPTION, icon, null, null);
    pane.putClientProperty(PopupFactory_FORCE_HEAVYWEIGHT_POPUP,
        Boolean.TRUE);
    Component fo = KeyboardFocusManager.getCurrentKeyboardFocusManager().
        getFocusOwner();

    pane.setWantsInput(true);
    pane.setSelectionValues(selectionValues);
    pane.setInitialSelectionValue(initialSelectionValue);

    JInternalFrame dialog =
        pane.createInternalFrame(parentComponent, title);

    pane.selectInitialValue();
    dialog.setVisible(true);

        /* Since all input will be blocked until this dialog is dismissed,
         * make sure its parent containers are visible first (this component
         * is tested below).  This is necessary for JApplets, because
         * because an applet normally isn't made visible until after its
         * start() method returns -- if this method is called from start(),
         * the applet will appear to hang while an invisible modal frame
         * waits for input.
         */
    if (dialog.isVisible() && !dialog.isShowing()) {
      Container parent = dialog.getParent();
      while (parent != null) {
        if (parent.isVisible() == false) {
          parent.setVisible(true);
        }
        parent = parent.getParent();
      }
    }

    // Use reflection to get Container.startLWModal.
    try {
      Method method = AccessController.doPrivileged(new ModalPrivilegedAction(
          Container.class, "startLWModal"));
      if (method != null) {
        method.invoke(dialog, (Object[]) null);
      }
    } catch (IllegalAccessException ex) {
    } catch (IllegalArgumentException ex) {
    } catch (InvocationTargetException ex) {
    }

    if (parentComponent instanceof JInternalFrame) {
      try {
        ((JInternalFrame) parentComponent).setSelected(true);
      } catch (java.beans.PropertyVetoException e) {
      }
    }

    if (fo != null && fo.isShowing()) {
      fo.requestFocus();
    }
    Object value = pane.getInputValue();

    if (value == UNINITIALIZED_VALUE) {
      return null;
    }
    return value;
  }

  /**
   * Creates and returns an instance of <code>JInternalFrame</code>.
   * The internal frame is created with the specified title,
   * and wrapping the <code>JOptionPane</code>.
   * The returned <code>JInternalFrame</code> is
   * added to the <code>JDesktopPane</code> ancestor of
   * <code>parentComponent</code>, or components
   * parent if one its ancestors isn't a <code>JDesktopPane</code>,
   * or if <code>parentComponent</code>
   * doesn't have a parent then a <code>RuntimeException</code> is thrown.
   *
   * @param parentComponent the parent <code>Component</code> for the internal frame
   * @param title the <code>String</code> to display in the frame's title bar
   * @return a <code>JInternalFrame</code> containing a <code>JOptionPane</code>
   * @throws RuntimeException if <code>parentComponent</code> does not have a valid parent
   */
  public JInternalFrame createInternalFrame(Component parentComponent,
      String title) {
    Container parent =
        JOptionPane.getDesktopPaneForComponent(parentComponent);

    if (parent == null && (parentComponent == null ||
        (parent = parentComponent.getParent()) == null)) {
      throw new RuntimeException("JOptionPane: parentComponent does " +
          "not have a valid parent");
    }

    // Option dialogs should be closable only
    final JInternalFrame iFrame = new JInternalFrame(title, false, true,
        false, false);

    iFrame.putClientProperty("JInternalFrame.frameType", "optionDialog");
    iFrame.putClientProperty("JInternalFrame.messageType",
        Integer.valueOf(getMessageType()));

    iFrame.addInternalFrameListener(new InternalFrameAdapter() {
      public void internalFrameClosing(InternalFrameEvent e) {
        if (getValue() == UNINITIALIZED_VALUE) {
          setValue(null);
        }
      }
    });
    addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent event) {
        // Let the defaultCloseOperation handle the closing
        // if the user closed the iframe without selecting a button
        // (newValue = null in that case).  Otherwise, close the dialog.
        if (iFrame.isVisible() &&
            event.getSource() == JOptionPane.this &&
            event.getPropertyName().equals(VALUE_PROPERTY)) {
          // Use reflection to get Container.stopLWModal().
          try {
            Method method = AccessController.doPrivileged(
                new ModalPrivilegedAction(
                    Container.class, "stopLWModal"));
            if (method != null) {
              method.invoke(iFrame, (Object[]) null);
            }
          } catch (IllegalAccessException ex) {
          } catch (IllegalArgumentException ex) {
          } catch (InvocationTargetException ex) {
          }

          try {
            iFrame.setClosed(true);
          } catch (java.beans.PropertyVetoException e) {
          }

          iFrame.setVisible(false);
        }
      }
    });
    iFrame.getContentPane().add(this, BorderLayout.CENTER);
    if (parent instanceof JDesktopPane) {
      parent.add(iFrame, JLayeredPane.MODAL_LAYER);
    } else {
      parent.add(iFrame, BorderLayout.CENTER);
    }
    Dimension iFrameSize = iFrame.getPreferredSize();
    Dimension rootSize = parent.getSize();
    Dimension parentSize = parentComponent.getSize();

    iFrame.setBounds((rootSize.width - iFrameSize.width) / 2,
        (rootSize.height - iFrameSize.height) / 2,
        iFrameSize.width, iFrameSize.height);
    // We want dialog centered relative to its parent component
    Point iFrameCoord =
        SwingUtilities.convertPoint(parentComponent, 0, 0, parent);
    int x = (parentSize.width - iFrameSize.width) / 2 + iFrameCoord.x;
    int y = (parentSize.height - iFrameSize.height) / 2 + iFrameCoord.y;

    // If possible, dialog should be fully visible
    int ovrx = x + iFrameSize.width - rootSize.width;
    int ovry = y + iFrameSize.height - rootSize.height;
    x = Math.max((ovrx > 0 ? x - ovrx : x), 0);
    y = Math.max((ovry > 0 ? y - ovry : y), 0);
    iFrame.setBounds(x, y, iFrameSize.width, iFrameSize.height);

    parent.validate();
    try {
      iFrame.setSelected(true);
    } catch (java.beans.PropertyVetoException e) {
    }

    return iFrame;
  }

  /**
   * Returns the specified component's <code>Frame</code>.
   *
   * @param parentComponent the <code>Component</code> to check for a <code>Frame</code>
   * @return the <code>Frame</code> that contains the component, or <code>getRootFrame</code> if the
   * component is <code>null</code>, or does not have a valid <code>Frame</code> parent
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see #getRootFrame
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public static Frame getFrameForComponent(Component parentComponent)
      throws HeadlessException {
    if (parentComponent == null) {
      return getRootFrame();
    }
    if (parentComponent instanceof Frame) {
      return (Frame) parentComponent;
    }
    return JOptionPane.getFrameForComponent(parentComponent.getParent());
  }

  /**
   * Returns the specified component's toplevel <code>Frame</code> or
   * <code>Dialog</code>.
   *
   * @param parentComponent the <code>Component</code> to check for a <code>Frame</code> or
   * <code>Dialog</code>
   * @return the <code>Frame</code> or <code>Dialog</code> that contains the component, or the
   * default frame if the component is <code>null</code>, or does not have a valid
   * <code>Frame</code> or <code>Dialog</code> parent
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  static Window getWindowForComponent(Component parentComponent)
      throws HeadlessException {
    if (parentComponent == null) {
      return getRootFrame();
    }
    if (parentComponent instanceof Frame || parentComponent instanceof Dialog) {
      return (Window) parentComponent;
    }
    return JOptionPane.getWindowForComponent(parentComponent.getParent());
  }


  /**
   * Returns the specified component's desktop pane.
   *
   * @param parentComponent the <code>Component</code> to check for a desktop
   * @return the <code>JDesktopPane</code> that contains the component, or <code>null</code> if the
   * component is <code>null</code> or does not have an ancestor that is a
   * <code>JInternalFrame</code>
   */
  public static JDesktopPane getDesktopPaneForComponent(Component parentComponent) {
    if (parentComponent == null) {
      return null;
    }
    if (parentComponent instanceof JDesktopPane) {
      return (JDesktopPane) parentComponent;
    }
    return getDesktopPaneForComponent(parentComponent.getParent());
  }

  private static final Object sharedFrameKey = JOptionPane.class;

  /**
   * Sets the frame to use for class methods in which a frame is
   * not provided.
   * <p>
   * <strong>Note:</strong>
   * It is recommended that rather than using this method you supply a valid parent.
   *
   * @param newRootFrame the default <code>Frame</code> to use
   */
  public static void setRootFrame(Frame newRootFrame) {
    if (newRootFrame != null) {
      SwingUtilities.appContextPut(sharedFrameKey, newRootFrame);
    } else {
      SwingUtilities.appContextRemove(sharedFrameKey);
    }
  }

  /**
   * Returns the <code>Frame</code> to use for the class methods in
   * which a frame is not provided.
   *
   * @return the default <code>Frame</code> to use
   * @throws HeadlessException if <code>GraphicsEnvironment.isHeadless</code> returns
   * <code>true</code>
   * @see #setRootFrame
   * @see java.awt.GraphicsEnvironment#isHeadless
   */
  public static Frame getRootFrame() throws HeadlessException {
    Frame sharedFrame =
        (Frame) SwingUtilities.appContextGet(sharedFrameKey);
    if (sharedFrame == null) {
      sharedFrame = SwingUtilities.getSharedOwnerFrame();
      SwingUtilities.appContextPut(sharedFrameKey, sharedFrame);
    }
    return sharedFrame;
  }

  /**
   * Creates a <code>JOptionPane</code> with a test message.
   */
  public JOptionPane() {
    this("JOptionPane message");
  }

  /**
   * Creates a instance of <code>JOptionPane</code> to display a
   * message using the
   * plain-message message type and the default options delivered by
   * the UI.
   *
   * @param message the <code>Object</code> to display
   */
  public JOptionPane(Object message) {
    this(message, PLAIN_MESSAGE);
  }

  /**
   * Creates an instance of <code>JOptionPane</code> to display a message
   * with the specified message type and the default options,
   *
   * @param message the <code>Object</code> to display
   * @param messageType the type of message to be displayed: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   */
  public JOptionPane(Object message, int messageType) {
    this(message, messageType, DEFAULT_OPTION);
  }

  /**
   * Creates an instance of <code>JOptionPane</code> to display a message
   * with the specified message type and options.
   *
   * @param message the <code>Object</code> to display
   * @param messageType the type of message to be displayed: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @param optionType the options to display in the pane: <code>DEFAULT_OPTION</code>,
   * <code>YES_NO_OPTION</code>, <code>YES_NO_CANCEL_OPTION</code>, <code>OK_CANCEL_OPTION</code>
   */
  public JOptionPane(Object message, int messageType, int optionType) {
    this(message, messageType, optionType, null);
  }

  /**
   * Creates an instance of <code>JOptionPane</code> to display a message
   * with the specified message type, options, and icon.
   *
   * @param message the <code>Object</code> to display
   * @param messageType the type of message to be displayed: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @param optionType the options to display in the pane: <code>DEFAULT_OPTION</code>,
   * <code>YES_NO_OPTION</code>, <code>YES_NO_CANCEL_OPTION</code>, <code>OK_CANCEL_OPTION</code>
   * @param icon the <code>Icon</code> image to display
   */
  public JOptionPane(Object message, int messageType, int optionType,
      Icon icon) {
    this(message, messageType, optionType, icon, null);
  }

  /**
   * Creates an instance of <code>JOptionPane</code> to display a message
   * with the specified message type, icon, and options.
   * None of the options is initially selected.
   * <p>
   * The options objects should contain either instances of
   * <code>Component</code>s, (which are added directly) or
   * <code>Strings</code> (which are wrapped in a <code>JButton</code>).
   * If you provide <code>Component</code>s, you must ensure that when the
   * <code>Component</code> is clicked it messages <code>setValue</code>
   * in the created <code>JOptionPane</code>.
   *
   * @param message the <code>Object</code> to display
   * @param messageType the type of message to be displayed: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @param optionType the options to display in the pane: <code>DEFAULT_OPTION</code>,
   * <code>YES_NO_OPTION</code>, <code>YES_NO_CANCEL_OPTION</code>, <code>OK_CANCEL_OPTION</code>
   * @param icon the <code>Icon</code> image to display
   * @param options the choices the user can select
   */
  public JOptionPane(Object message, int messageType, int optionType,
      Icon icon, Object[] options) {
    this(message, messageType, optionType, icon, options, null);
  }

  /**
   * Creates an instance of <code>JOptionPane</code> to display a message
   * with the specified message type, icon, and options, with the
   * initially-selected option specified.
   *
   * @param message the <code>Object</code> to display
   * @param messageType the type of message to be displayed: <code>ERROR_MESSAGE</code>,
   * <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>, <code>QUESTION_MESSAGE</code>,
   * or <code>PLAIN_MESSAGE</code>
   * @param optionType the options to display in the pane: <code>DEFAULT_OPTION</code>,
   * <code>YES_NO_OPTION</code>, <code>YES_NO_CANCEL_OPTION</code>, <code>OK_CANCEL_OPTION</code>
   * @param icon the Icon image to display
   * @param options the choices the user can select
   * @param initialValue the choice that is initially selected; if <code>null</code>, then nothing
   * will be initially selected; only meaningful if <code>options</code> is used
   */
  public JOptionPane(Object message, int messageType, int optionType,
      Icon icon, Object[] options, Object initialValue) {

    this.message = message;
    this.options = options;
    this.initialValue = initialValue;
    this.icon = icon;
    setMessageType(messageType);
    setOptionType(optionType);
    value = UNINITIALIZED_VALUE;
    inputValue = UNINITIALIZED_VALUE;
    updateUI();
  }

  /**
   * Sets the UI object which implements the {@literal L&F} for this component.
   *
   * @param ui the <code>OptionPaneUI</code> {@literal L&F} object
   * @beaninfo bound: true hidden: true description: The UI object that implements the optionpane's
   * LookAndFeel
   * @see UIDefaults#getUI
   */
  public void setUI(OptionPaneUI ui) {
    if (this.ui != ui) {
      super.setUI(ui);
      invalidate();
    }
  }

  /**
   * Returns the UI object which implements the {@literal L&F} for this component.
   *
   * @return the <code>OptionPaneUI</code> object
   */
  public OptionPaneUI getUI() {
    return (OptionPaneUI) ui;
  }

  /**
   * Notification from the <code>UIManager</code> that the {@literal L&F} has changed.
   * Replaces the current UI object with the latest version from the
   * <code>UIManager</code>.
   *
   * @see JComponent#updateUI
   */
  public void updateUI() {
    setUI((OptionPaneUI) UIManager.getUI(this));
  }


  /**
   * Returns the name of the UI class that implements the
   * {@literal L&F} for this component.
   *
   * @return the string "OptionPaneUI"
   * @see JComponent#getUIClassID
   * @see UIDefaults#getUI
   */
  public String getUIClassID() {
    return uiClassID;
  }


  /**
   * Sets the option pane's message-object.
   *
   * @param newMessage the <code>Object</code> to display
   * @beaninfo preferred: true bound: true description: The optionpane's message object.
   * @see #getMessage
   */
  public void setMessage(Object newMessage) {
    Object oldMessage = message;

    message = newMessage;
    firePropertyChange(MESSAGE_PROPERTY, oldMessage, message);
  }

  /**
   * Returns the message-object this pane displays.
   *
   * @return the <code>Object</code> that is displayed
   * @see #setMessage
   */
  public Object getMessage() {
    return message;
  }

  /**
   * Sets the icon to display. If non-<code>null</code>, the look and feel
   * does not provide an icon.
   *
   * @param newIcon the <code>Icon</code> to display
   * @beaninfo preferred: true bound: true description: The option pane's type icon.
   * @see #getIcon
   */
  public void setIcon(Icon newIcon) {
    Object oldIcon = icon;

    icon = newIcon;
    firePropertyChange(ICON_PROPERTY, oldIcon, icon);
  }

  /**
   * Returns the icon this pane displays.
   *
   * @return the <code>Icon</code> that is displayed
   * @see #setIcon
   */
  public Icon getIcon() {
    return icon;
  }

  /**
   * Sets the value the user has chosen.
   *
   * @param newValue the chosen value
   * @beaninfo preferred: true bound: true description: The option pane's value object.
   * @see #getValue
   */
  public void setValue(Object newValue) {
    Object oldValue = value;

    value = newValue;
    firePropertyChange(VALUE_PROPERTY, oldValue, value);
  }

  /**
   * Returns the value the user has selected. <code>UNINITIALIZED_VALUE</code>
   * implies the user has not yet made a choice, <code>null</code> means the
   * user closed the window with out choosing anything. Otherwise
   * the returned value will be one of the options defined in this
   * object.
   *
   * @return the <code>Object</code> chosen by the user, <code>UNINITIALIZED_VALUE</code> if the
   * user has not yet made a choice, or <code>null</code> if the user closed the window without
   * making a choice
   * @see #setValue
   */
  public Object getValue() {
    return value;
  }

  /**
   * Sets the options this pane displays. If an element in
   * <code>newOptions</code> is a <code>Component</code>
   * it is added directly to the pane,
   * otherwise a button is created for the element.
   *
   * @param newOptions an array of <code>Objects</code> that create the buttons the user can click
   * on, or arbitrary <code>Components</code> to add to the pane
   * @beaninfo bound: true description: The option pane's options objects.
   * @see #getOptions
   */
  public void setOptions(Object[] newOptions) {
    Object[] oldOptions = options;

    options = newOptions;
    firePropertyChange(OPTIONS_PROPERTY, oldOptions, options);
  }

  /**
   * Returns the choices the user can make.
   *
   * @return the array of <code>Objects</code> that give the user's choices
   * @see #setOptions
   */
  public Object[] getOptions() {
    if (options != null) {
      int optionCount = options.length;
      Object[] retOptions = new Object[optionCount];

      System.arraycopy(options, 0, retOptions, 0, optionCount);
      return retOptions;
    }
    return options;
  }

  /**
   * Sets the initial value that is to be enabled -- the
   * <code>Component</code>
   * that has the focus when the pane is initially displayed.
   *
   * @param newInitialValue the <code>Object</code> that gets the initial keyboard focus
   * @beaninfo preferred: true bound: true description: The option pane's initial value object.
   * @see #getInitialValue
   */
  public void setInitialValue(Object newInitialValue) {
    Object oldIV = initialValue;

    initialValue = newInitialValue;
    firePropertyChange(INITIAL_VALUE_PROPERTY, oldIV, initialValue);
  }

  /**
   * Returns the initial value.
   *
   * @return the <code>Object</code> that gets the initial keyboard focus
   * @see #setInitialValue
   */
  public Object getInitialValue() {
    return initialValue;
  }

  /**
   * Sets the option pane's message type.
   * The message type is used by the Look and Feel to determine the
   * icon to display (if not supplied) as well as potentially how to
   * lay out the <code>parentComponent</code>.
   *
   * @param newType an integer specifying the kind of message to display:
   * <code>ERROR_MESSAGE</code>, <code>INFORMATION_MESSAGE</code>, <code>WARNING_MESSAGE</code>,
   * <code>QUESTION_MESSAGE</code>, or <code>PLAIN_MESSAGE</code>
   * @throws RuntimeException if <code>newType</code> is not one of the legal values listed above
   * @beaninfo preferred: true bound: true description: The option pane's message type.
   * @see #getMessageType
   */
  public void setMessageType(int newType) {
    if (newType != ERROR_MESSAGE && newType != INFORMATION_MESSAGE &&
        newType != WARNING_MESSAGE && newType != QUESTION_MESSAGE &&
        newType != PLAIN_MESSAGE) {
      throw new RuntimeException(
          "JOptionPane: type must be one of JOptionPane.ERROR_MESSAGE, JOptionPane.INFORMATION_MESSAGE, JOptionPane.WARNING_MESSAGE, JOptionPane.QUESTION_MESSAGE or JOptionPane.PLAIN_MESSAGE");
    }

    int oldType = messageType;

    messageType = newType;
    firePropertyChange(MESSAGE_TYPE_PROPERTY, oldType, messageType);
  }

  /**
   * Returns the message type.
   *
   * @return an integer specifying the message type
   * @see #setMessageType
   */
  public int getMessageType() {
    return messageType;
  }

  /**
   * Sets the options to display.
   * The option type is used by the Look and Feel to
   * determine what buttons to show (unless options are supplied).
   *
   * @param newType an integer specifying the options the {@literal L&F} is to display:
   * <code>DEFAULT_OPTION</code>, <code>YES_NO_OPTION</code>, <code>YES_NO_CANCEL_OPTION</code>, or
   * <code>OK_CANCEL_OPTION</code>
   * @throws RuntimeException if <code>newType</code> is not one of the legal values listed above
   * @beaninfo preferred: true bound: true description: The option pane's option type.
   * @see #getOptionType
   * @see #setOptions
   */
  public void setOptionType(int newType) {
    if (newType != DEFAULT_OPTION && newType != YES_NO_OPTION &&
        newType != YES_NO_CANCEL_OPTION && newType != OK_CANCEL_OPTION) {
      throw new RuntimeException(
          "JOptionPane: option type must be one of JOptionPane.DEFAULT_OPTION, JOptionPane.YES_NO_OPTION, JOptionPane.YES_NO_CANCEL_OPTION or JOptionPane.OK_CANCEL_OPTION");
    }

    int oldType = optionType;

    optionType = newType;
    firePropertyChange(OPTION_TYPE_PROPERTY, oldType, optionType);
  }

  /**
   * Returns the type of options that are displayed.
   *
   * @return an integer specifying the user-selectable options
   * @see #setOptionType
   */
  public int getOptionType() {
    return optionType;
  }

  /**
   * Sets the input selection values for a pane that provides the user
   * with a list of items to choose from. (The UI provides a widget
   * for choosing one of the values.)  A <code>null</code> value
   * implies the user can input whatever they wish, usually by means
   * of a <code>JTextField</code>.
   * <p>
   * Sets <code>wantsInput</code> to true. Use
   * <code>setInitialSelectionValue</code> to specify the initially-chosen
   * value. After the pane as been enabled, <code>inputValue</code> is
   * set to the value the user has selected.
   *
   * @param newValues an array of <code>Objects</code> the user to be displayed (usually in a list
   * or combo-box) from which the user can make a selection
   * @beaninfo bound: true description: The option pane's selection values.
   * @see #setWantsInput
   * @see #setInitialSelectionValue
   * @see #getSelectionValues
   */
  public void setSelectionValues(Object[] newValues) {
    Object[] oldValues = selectionValues;

    selectionValues = newValues;
    firePropertyChange(SELECTION_VALUES_PROPERTY, oldValues, newValues);
    if (selectionValues != null) {
      setWantsInput(true);
    }
  }

  /**
   * Returns the input selection values.
   *
   * @return the array of <code>Objects</code> the user can select
   * @see #setSelectionValues
   */
  public Object[] getSelectionValues() {
    return selectionValues;
  }

  /**
   * Sets the input value that is initially displayed as selected to the user.
   * Only used if <code>wantsInput</code> is true.
   *
   * @param newValue the initially selected value
   * @beaninfo bound: true description: The option pane's initial selection value object.
   * @see #setSelectionValues
   * @see #getInitialSelectionValue
   */
  public void setInitialSelectionValue(Object newValue) {
    Object oldValue = initialSelectionValue;

    initialSelectionValue = newValue;
    firePropertyChange(INITIAL_SELECTION_VALUE_PROPERTY, oldValue,
        newValue);
  }

  /**
   * Returns the input value that is displayed as initially selected to the user.
   *
   * @return the initially selected value
   * @see #setInitialSelectionValue
   * @see #setSelectionValues
   */
  public Object getInitialSelectionValue() {
    return initialSelectionValue;
  }

  /**
   * Sets the input value that was selected or input by the user.
   * Only used if <code>wantsInput</code> is true.  Note that this method
   * is invoked internally by the option pane (in response to user action)
   * and should generally not be called by client programs.  To set the
   * input value initially displayed as selected to the user, use
   * <code>setInitialSelectionValue</code>.
   *
   * @param newValue the <code>Object</code> used to set the value that the user specified (usually
   * in a text field)
   * @beaninfo preferred: true bound: true description: The option pane's input value object.
   * @see #setSelectionValues
   * @see #setInitialSelectionValue
   * @see #setWantsInput
   * @see #getInputValue
   */
  public void setInputValue(Object newValue) {
    Object oldValue = inputValue;

    inputValue = newValue;
    firePropertyChange(INPUT_VALUE_PROPERTY, oldValue, newValue);
  }

  /**
   * Returns the value the user has input, if <code>wantsInput</code>
   * is true.
   *
   * @return the <code>Object</code> the user specified, if it was one of the objects, or a
   * <code>String</code> if it was a value typed into a field
   * @see #setSelectionValues
   * @see #setWantsInput
   * @see #setInputValue
   */
  public Object getInputValue() {
    return inputValue;
  }

  /**
   * Returns the maximum number of characters to place on a line in a
   * message. Default is to return <code>Integer.MAX_VALUE</code>.
   * The value can be
   * changed by overriding this method in a subclass.
   *
   * @return an integer giving the maximum number of characters on a line
   */
  public int getMaxCharactersPerLineCount() {
    return Integer.MAX_VALUE;
  }

  /**
   * Sets the <code>wantsInput</code> property.
   * If <code>newValue</code> is true, an input component
   * (such as a text field or combo box) whose parent is
   * <code>parentComponent</code> is provided to
   * allow the user to input a value. If <code>getSelectionValues</code>
   * returns a non-<code>null</code> array, the input value is one of the
   * objects in that array. Otherwise the input value is whatever
   * the user inputs.
   * <p>
   * This is a bound property.
   *
   * @beaninfo preferred: true bound: true description: Flag which allows the user to input a
   * value.
   * @see #setSelectionValues
   * @see #setInputValue
   */
  public void setWantsInput(boolean newValue) {
    boolean oldValue = wantsInput;

    wantsInput = newValue;
    firePropertyChange(WANTS_INPUT_PROPERTY, oldValue, newValue);
  }

  /**
   * Returns the value of the <code>wantsInput</code> property.
   *
   * @return true if an input component will be provided
   * @see #setWantsInput
   */
  public boolean getWantsInput() {
    return wantsInput;
  }

  /**
   * Requests that the initial value be selected, which will set
   * focus to the initial value. This method
   * should be invoked after the window containing the option pane
   * is made visible.
   */
  public void selectInitialValue() {
    OptionPaneUI ui = getUI();
    if (ui != null) {
      ui.selectInitialValue(this);
    }
  }


  private static int styleFromMessageType(int messageType) {
    switch (messageType) {
      case ERROR_MESSAGE:
        return JRootPane.ERROR_DIALOG;
      case QUESTION_MESSAGE:
        return JRootPane.QUESTION_DIALOG;
      case WARNING_MESSAGE:
        return JRootPane.WARNING_DIALOG;
      case INFORMATION_MESSAGE:
        return JRootPane.INFORMATION_DIALOG;
      case PLAIN_MESSAGE:
      default:
        return JRootPane.PLAIN_DIALOG;
    }
  }

  // Serialization support.
  private void writeObject(ObjectOutputStream s) throws IOException {
    Vector<Object> values = new Vector<Object>();

    s.defaultWriteObject();
    // Save the icon, if its Serializable.
    if (icon != null && icon instanceof Serializable) {
      values.addElement("icon");
      values.addElement(icon);
    }
    // Save the message, if its Serializable.
    if (message != null && message instanceof Serializable) {
      values.addElement("message");
      values.addElement(message);
    }
    // Save the treeModel, if its Serializable.
    if (options != null) {
      Vector<Object> serOptions = new Vector<Object>();

      for (int counter = 0, maxCounter = options.length;
          counter < maxCounter; counter++) {
        if (options[counter] instanceof Serializable) {
          serOptions.addElement(options[counter]);
        }
      }
      if (serOptions.size() > 0) {
        int optionCount = serOptions.size();
        Object[] arrayOptions = new Object[optionCount];

        serOptions.copyInto(arrayOptions);
        values.addElement("options");
        values.addElement(arrayOptions);
      }
    }
    // Save the initialValue, if its Serializable.
    if (initialValue != null && initialValue instanceof Serializable) {
      values.addElement("initialValue");
      values.addElement(initialValue);
    }
    // Save the value, if its Serializable.
    if (value != null && value instanceof Serializable) {
      values.addElement("value");
      values.addElement(value);
    }
    // Save the selectionValues, if its Serializable.
    if (selectionValues != null) {
      boolean serialize = true;

      for (int counter = 0, maxCounter = selectionValues.length;
          counter < maxCounter; counter++) {
        if (selectionValues[counter] != null &&
            !(selectionValues[counter] instanceof Serializable)) {
          serialize = false;
          break;
        }
      }
      if (serialize) {
        values.addElement("selectionValues");
        values.addElement(selectionValues);
      }
    }
    // Save the inputValue, if its Serializable.
    if (inputValue != null && inputValue instanceof Serializable) {
      values.addElement("inputValue");
      values.addElement(inputValue);
    }
    // Save the initialSelectionValue, if its Serializable.
    if (initialSelectionValue != null &&
        initialSelectionValue instanceof Serializable) {
      values.addElement("initialSelectionValue");
      values.addElement(initialSelectionValue);
    }
    s.writeObject(values);
  }

  private void readObject(ObjectInputStream s)
      throws IOException, ClassNotFoundException {
    s.defaultReadObject();

    Vector values = (Vector) s.readObject();
    int indexCounter = 0;
    int maxCounter = values.size();

    if (indexCounter < maxCounter && values.elementAt(indexCounter).
        equals("icon")) {
      icon = (Icon) values.elementAt(++indexCounter);
      indexCounter++;
    }
    if (indexCounter < maxCounter && values.elementAt(indexCounter).
        equals("message")) {
      message = values.elementAt(++indexCounter);
      indexCounter++;
    }
    if (indexCounter < maxCounter && values.elementAt(indexCounter).
        equals("options")) {
      options = (Object[]) values.elementAt(++indexCounter);
      indexCounter++;
    }
    if (indexCounter < maxCounter && values.elementAt(indexCounter).
        equals("initialValue")) {
      initialValue = values.elementAt(++indexCounter);
      indexCounter++;
    }
    if (indexCounter < maxCounter && values.elementAt(indexCounter).
        equals("value")) {
      value = values.elementAt(++indexCounter);
      indexCounter++;
    }
    if (indexCounter < maxCounter && values.elementAt(indexCounter).
        equals("selectionValues")) {
      selectionValues = (Object[]) values.elementAt(++indexCounter);
      indexCounter++;
    }
    if (indexCounter < maxCounter && values.elementAt(indexCounter).
        equals("inputValue")) {
      inputValue = values.elementAt(++indexCounter);
      indexCounter++;
    }
    if (indexCounter < maxCounter && values.elementAt(indexCounter).
        equals("initialSelectionValue")) {
      initialSelectionValue = values.elementAt(++indexCounter);
      indexCounter++;
    }
    if (getUIClassID().equals(uiClassID)) {
      byte count = JComponent.getWriteObjCounter(this);
      JComponent.setWriteObjCounter(this, --count);
      if (count == 0 && ui != null) {
        ui.installUI(this);
      }
    }
  }


  /**
   * Returns a string representation of this <code>JOptionPane</code>.
   * This method
   * is intended to be used only for debugging purposes, and the
   * content and format of the returned string may vary between
   * implementations. The returned string may be empty but may not
   * be <code>null</code>.
   *
   * @return a string representation of this <code>JOptionPane</code>
   */
  protected String paramString() {
    String iconString = (icon != null ?
        icon.toString() : "");
    String initialValueString = (initialValue != null ?
        initialValue.toString() : "");
    String messageString = (message != null ?
        message.toString() : "");
    String messageTypeString;
    if (messageType == ERROR_MESSAGE) {
      messageTypeString = "ERROR_MESSAGE";
    } else if (messageType == INFORMATION_MESSAGE) {
      messageTypeString = "INFORMATION_MESSAGE";
    } else if (messageType == WARNING_MESSAGE) {
      messageTypeString = "WARNING_MESSAGE";
    } else if (messageType == QUESTION_MESSAGE) {
      messageTypeString = "QUESTION_MESSAGE";
    } else if (messageType == PLAIN_MESSAGE) {
      messageTypeString = "PLAIN_MESSAGE";
    } else {
      messageTypeString = "";
    }
    String optionTypeString;
    if (optionType == DEFAULT_OPTION) {
      optionTypeString = "DEFAULT_OPTION";
    } else if (optionType == YES_NO_OPTION) {
      optionTypeString = "YES_NO_OPTION";
    } else if (optionType == YES_NO_CANCEL_OPTION) {
      optionTypeString = "YES_NO_CANCEL_OPTION";
    } else if (optionType == OK_CANCEL_OPTION) {
      optionTypeString = "OK_CANCEL_OPTION";
    } else {
      optionTypeString = "";
    }
    String wantsInputString = (wantsInput ?
        "true" : "false");

    return super.paramString() +
        ",icon=" + iconString +
        ",initialValue=" + initialValueString +
        ",message=" + messageString +
        ",messageType=" + messageTypeString +
        ",optionType=" + optionTypeString +
        ",wantsInput=" + wantsInputString;
  }

  /**
   * Retrieves a method from the provided class and makes it accessible.
   */
  private static class ModalPrivilegedAction implements PrivilegedAction<Method> {

    private Class<?> clazz;
    private String methodName;

    public ModalPrivilegedAction(Class<?> clazz, String methodName) {
      this.clazz = clazz;
      this.methodName = methodName;
    }

    public Method run() {
      Method method = null;
      try {
        method = clazz.getDeclaredMethod(methodName, (Class[]) null);
      } catch (NoSuchMethodException ex) {
      }
      if (method != null) {
        method.setAccessible(true);
      }
      return method;
    }
  }

///////////////////
// Accessibility support
///////////////////

  /**
   * Returns the <code>AccessibleContext</code> associated with this JOptionPane.
   * For option panes, the <code>AccessibleContext</code> takes the form of an
   * <code>AccessibleJOptionPane</code>.
   * A new <code>AccessibleJOptionPane</code> instance is created if necessary.
   *
   * @return an AccessibleJOptionPane that serves as the AccessibleContext of this
   * AccessibleJOptionPane
   * @beaninfo expert: true description: The AccessibleContext associated with this option pane
   */
  public AccessibleContext getAccessibleContext() {
    if (accessibleContext == null) {
      accessibleContext = new AccessibleJOptionPane();
    }
    return accessibleContext;
  }

  /**
   * This class implements accessibility support for the
   * <code>JOptionPane</code> class.  It provides an implementation of the
   * Java Accessibility API appropriate to option pane user-interface
   * elements.
   * <p>
   * <strong>Warning:</strong>
   * Serialized objects of this class will not be compatible with
   * future Swing releases. The current serialization support is
   * appropriate for short term storage or RMI between applications running
   * the same version of Swing.  As of 1.4, support for long term storage
   * of all JavaBeans&trade;
   * has been added to the <code>java.beans</code> package.
   * Please see {@link java.beans.XMLEncoder}.
   */
  protected class AccessibleJOptionPane extends AccessibleJComponent {

    /**
     * Get the role of this object.
     *
     * @return an instance of AccessibleRole describing the role of the object
     * @see AccessibleRole
     */
    public AccessibleRole getAccessibleRole() {
      switch (messageType) {
        case ERROR_MESSAGE:
        case INFORMATION_MESSAGE:
        case WARNING_MESSAGE:
          return AccessibleRole.ALERT;

        default:
          return AccessibleRole.OPTION_PANE;
      }
    }

  } // inner class AccessibleJOptionPane
}
